Unity 世界坐标、屏幕坐标、UGUI 坐标 相互转换

您所在的位置:网站首页 unity ui摄像机 Unity 世界坐标、屏幕坐标、UGUI 坐标 相互转换

Unity 世界坐标、屏幕坐标、UGUI 坐标 相互转换

2023-08-11 07:45| 来源: 网络整理| 查看: 265

Unity 世界坐标、屏幕坐标、UGUI 坐标 相互转换 坐标转换是游戏开发过程中必不可少的环节 看下图 世界坐标、屏幕坐标、UI 坐标 三种坐标系的转换过程,此文章中的 UI 坐标特指 UGUI 坐标

从上图可以看到,世界坐标 和 UI 坐标 需要通过 屏幕坐标作为中间转换媒介 世界坐标 -> 屏幕坐标 -> UI 坐标 UI 坐标 -> 屏幕坐标 -> 世界坐标

屏幕坐标为 从屏幕左下角开始 坐标为 Vector2 (0, 0), 右上角结束坐标为 Vector2(Screen.width, Screen.height)

关于屏幕的坐标还有一个视口坐标 (Viewport) 视口坐标为 从屏幕左下角开始 坐标为 Vector2 (0, 0), 右上角结束坐标为 Vector2(1, 1) 本篇省略 视口坐标的转换

代码如下

首先提供一个获取 UI 摄像机的方法 UGUI 中 Canvas 的 renderMode 分为 RenderMode.ScreenSpaceOverlay、 RenderMode.ScreenSpaceCamera、 RenderMode.WorldSpace

其中 RenderMode.ScreenSpaceOverlay 不需要摄像机,其他两种需要摄像机,所以 UIManager 类需要根据 renderMode 类型处理 UICamera 的获取

public class UIManager : MonoBehaviour { public static UIManager Instance; public Camera UICamera;

// Start is called before the first frame update void Start() { Instance = this; Canvas canvas = GameObject.Find("Canvas").GetComponent(); if ( canvas.renderMode == RenderMode.ScreenSpaceCamera || canvas.renderMode == RenderMode.WorldSpace) { UICamera = canvas.worldCamera; } else if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) { UICamera = null; } } public static UIManager GetInstance() { return Instance; }

}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 using UnityEngine;

public class PositionConvert {

/// /// 世界坐标转换为屏幕坐标 /// /// 屏幕坐标 /// public static Vector2 WorldPointToScreenPoint(Vector3 worldPoint) { // Camera.main 世界摄像机 Vector2 screenPoint = Camera.main.WorldToScreenPoint(worldPoint); return screenPoint; } /// /// 屏幕坐标转换为世界坐标 /// /// 屏幕坐标 /// 距离摄像机 Z 平面的距离 /// public static Vector3 ScreenPointToWorldPoint(Vector2 screenPoint, float planeZ) { // Camera.main 世界摄像机 Vector3 position = new Vector3(screenPoint.x, screenPoint.y, planeZ); Vector3 worldPoint = Camera.main.ScreenToWorldPoint(position); return worldPoint; } / // RectTransformUtility.WorldToScreenPoint // RectTransformUtility.ScreenPointToWorldPointInRectangle // RectTransformUtility.ScreenPointToLocalPointInRectangle // 上面三个坐标转换的方法使用 Camera 的地方 // 当 Canvas renderMode 为 RenderMode.ScreenSpaceCamera、RenderMode.WorldSpace 时 传递参数 canvas.worldCamera // 当 Canvas renderMode 为 RenderMode.ScreenSpaceOverlay 时 传递参数 null // UI 坐标转换为屏幕坐标 public static Vector2 UIPointToScreenPoint(Vector3 worldPoint) { // RectTransform:target // worldPoint = target.position; Camera uiCamera = UIManager.GetInstance().UICamera; Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(uiCamera, worldPoint); return screenPoint; } // 屏幕坐标转换为 UGUI 坐标 public static Vector3 ScreenPointToUIPoint(RectTransform rt, Vector2 screenPoint) { Vector3 globalMousePos; //UI屏幕坐标转换为世界坐标 Camera uiCamera = UIManager.GetInstance().UICamera; // 当 Canvas renderMode 为 RenderMode.ScreenSpaceCamera、RenderMode.WorldSpace 时 uiCamera 不能为空 // 当 Canvas renderMode 为 RenderMode.ScreenSpaceOverlay 时 uiCamera 可以为空 RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, screenPoint, uiCamera, out globalMousePos); // 转换后的 globalMousePos 使用下面方法赋值 // target 为需要使用的 UI RectTransform // rt 可以是 target.GetComponent(), 也可以是 target.parent.GetComponent() // target.transform.position = globalMousePos; return globalMousePos; } // 屏幕坐标转换为 UGUI RectTransform 的 anchoredPosition public static Vector2 ScreenPointToUILocalPoint(RectTransform parentRT, Vector2 screenPoint) { Vector2 localPos; Camera uiCamera = UIManager.GetInstance().UICamera; RectTransformUtility.ScreenPointToLocalPointInRectangle(parentRT, screenPoint, uiCamera, out localPos); // 转换后的 localPos 使用下面方法赋值 // target 为需要使用的 UI RectTransform // parentRT 是 target.parent.GetComponent() // 最后赋值 target.anchoredPosition = localPos; return localPos; }

}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 使用方法如下

世界坐标 -> 屏幕坐标

GameObject go = GameObject.Find("GO"); Vector2 screenPoint = PositionConvert.WorldPointToScreenPoint(go.transform.position);

1 2 屏幕坐标-> 世界坐标

Vector2 screenPoint = new Vector2(100, 100); // 距离摄像机 Z 轴方向距离为 10 float planeZ = 10; Vector3 worldPoint = PositionConvert.ScreenPointToWorldPoint(screenPoint, planeZ);

1 2 3 4 UI 坐标 -> 屏幕坐标

// 获取 UGUI 组件 transform Transform dst = GameObject.Find("Canvas/Panel/Image").transform; // 将 UI transform.position 坐标转换为屏幕坐标 Vector2 screenPoint = PositionConvert.UIPointToScreenPoint(dst.position);

1 2 3 4 屏幕坐标 -> UI 坐标 方法一

GameObject target = GameObject.Find("Canvas/Panel1/target"); RectTransform rt = target.GetComponent(); // 将屏幕坐标转换为 UI transform.position Vector3 uiPoint = PositionConvert.ScreenPointToUIPoint(rt, screenPoint); target.transform.position = uiPoint;

1 2 3 4 5 6 屏幕坐标 -> UI 坐标 方法二

GameObject target = GameObject.Find("Canvas/Panel1/target"); RectTransform targetRt = target.GetComponent(); // target Parent Transform parent = target.transform.parent; RectTransform parentRt = parent.GetComponent(); // 将屏幕坐标转换为 UI transform.position Vector3 uiPoint = PositionConvert.ScreenPointToUILocalPoint(parentRt, screenPoint); targetRt.anchoredPosition = uiPoint;

1 2 3 4 5 6 7 8 9 10 代码中注释比较详细,就不细说了,使用上面方法,无论 Canvas 的 renderMode 使用哪种类型,代码执行结果都是正确的 ———————————————— 版权声明:本文为CSDN博主「[奋斗不止]」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/LIQIANGEASTSUN/article/details/124413387



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3